﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class GameObjectPool
{
    public int id = -1;

    private Object prefab;
    private int totalObjCount = 0;

    private List<GameObject> available = new List<GameObject>();
    private List<GameObject> allObject = new List<GameObject>();
    public HashSet<string> strKeys = new HashSet<string>();
    private GameObjectPoolManager manager;
    public GameObjectPool(Object obj, int num, int id,GameObjectPoolManager manager)
    {
        prefab = obj;
        this.id = id;
        this.manager = manager;
        PrePopulate(num);
    }

    public void MatchPopulation(int num)
    {
        PrePopulate(num - totalObjCount);
    }

    public void PrePopulate(int num)
    {
        for (int i = totalObjCount; i < num; i++)
        {
            GameObject obj = (GameObject)Object.Instantiate(prefab);
            obj.name = prefab.name + "_"+id;
            manager.AddId(obj.GetInstanceID(), id);
            //obj.AddComponent<GameObjectPoolId>().id = id;
            available.Add(obj);
            allObject.Add(obj);
            totalObjCount++;
            obj.SetActive(false);
        }
    }

    public void AddKey(string key)
    {
        if(strKeys.Contains(key))
        {
            Debug.LogError(key+" exist key in pool " + prefab.name);
        }
        else
        {
            strKeys.Add(key);
        }
    }

    public GameObject Spawn()
    {
        GameObject spawnObj;

        if (available.Count > 0)
        {
            spawnObj = available[0];
            available.RemoveAt(0);
            spawnObj.SetActive(true);
        }
        else
        {
            spawnObj = (GameObject)GameObject.Instantiate(prefab);
            spawnObj.name = prefab.name + "_" + id;
            manager.AddId(spawnObj.GetInstanceID(), id);
            //spawnObj.AddComponent<GameObjectPoolId>().id = id;
            allObject.Add(spawnObj);
            totalObjCount += 1;
        }

        return spawnObj;
    }

    public void Unspawn(GameObject obj)
    {
        if (available.IndexOf(obj) == -1)
        {
            available.Add(obj);
        }
        obj.SetActive(false);
    }

    public void UnspawnAll()
    {
        foreach (GameObject obj in allObject)
        {
            if (obj != null)
            {
                manager.RemoveId(obj.GetInstanceID());
                GameObject.Destroy(obj);
            }
        }
        allObject.Clear();
    }

    public bool UnspawnAll(string key)
    {
        if(strKeys.Contains(key))
        {
            strKeys.Remove(key);
            if (strKeys.Count == 0)
            {
                UnspawnAll();
                return true;
            }
            else
            {
                for(int i = available.Count - 1; i >= available.Count / 2;--i)
                {
                    manager.RemoveId(available[i].GetInstanceID());
                    GameObject.Destroy(available[i]);
                    available.RemoveAt(i);
                }
                return false;
            }
        }
        else
        {
            Debug.LogError("unspawn error " + prefab.name + " with no key " + key);
            //UnspawnAll();
            return false;
        }
    }

    public void HideInHierarchy(Transform t)
    {
        foreach (GameObject obj in available)
        {
            obj.transform.parent = t;
        }
    }

    public Object GetPrefab()
    {
        return prefab;
    }

    public int TotalCount
    {
        get
        {
            return totalObjCount;
        }
    }
}
